﻿using Synthesize.BaseSet.Domain.Repository.Authority;
using Synthesize.BaseSet.ServiceInterface.Query.Authority;
using Library.Core.Application.BaseAction;
using Library.Core.Application.IInfrastructure;
using Library.Common.Model;
using System.Threading.Tasks;
using System.Collections.Generic;
using System;
using System.Linq;
using Library.Common.Common;
using Synthesize.BaseSet.ServiceInterface.Dtos.Authority.Menu;
using Synthesize.BaseSet.Domain.Aggregation.Entity.Authority;
using Synthesize.BaseSet.Domain.Specifications.Authority.Menu;
using Library.Common.Serialize;
using Library.Core.Application;
using Synthesize.BaseSet.Domain.Aggregation.Dtos.Authority.Menu;

namespace Synthesize.BaseSet.Application.Query.Authority
{
    public class MenuQueryService : BaseService, IMenuQueryService
    {
        private readonly IMenuRepository _menuRepository;
        private readonly IMenuPermissionRepository _menuPermissionRepository;
        private readonly IRoleMenuPermissionRepository _roleMenuPermissionRepository;
        private readonly IUserRepository _userRepository;
        private readonly IUserRoleRepository _userRoleRepository;


        public MenuQueryService(IIocContainer container
            , IMenuRepository menuRepository
            , IMenuPermissionRepository menuPermissionRepository
            , IRoleMenuPermissionRepository roleMenuPermissionRepository
            , IUserRepository userRepository
            , IUserRoleRepository userRoleRepository

            ) : base(container)
        {
            _menuRepository = menuRepository;
            _menuPermissionRepository = menuPermissionRepository;
            _roleMenuPermissionRepository = roleMenuPermissionRepository;
            _userRepository = userRepository;
            _userRoleRepository = userRoleRepository;
        }

        #region 获取用户可操作菜单信息

        /// <summary>
        /// 获取用户可操作菜单信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<GetUserMenuOutput>> GetMenuByUser(GetUserMenuIntput input)
        {

            return await HandleAsync(async () =>
            {
                var result = new GetUserMenuOutput();

                var userInfo = await _userRepository.GetAsync(x => x.UserName == input.UserName);
                if (userInfo == null)
                {
                    throw new ApplicationsException("无对应用户信息.");
                }

                //如果是超级管理员，就直接获取所有的操作
                if (userInfo.IsSuperUser)
                {
                    var menuList = await _menuRepository.GetManyAsync(x => x.Platform == input.Platform, orderbys: (x => x.Sort, true));
                    if (menuList.Any())
                    {
                        #region UserMenus

                        var roots = menuList.Where(x => !x.ParentId.HasValue).ToList();
                        foreach (var item in roots)
                        {
                            var userMenu = new UserMenuInfo()
                            {
                                Component = item.Component,//加载的页面组件位置，系统将自动组装成() => import(/* webpackChunkName: "home" */ '@/views/home') 的形式。
                                Name = item.Name,//路由的标识，必填且与页面组件的name一致，否则 < keep - alive > 页面缓存效果失效。
                                Path = item.Path,//路由在游览器地址栏里的hash值，也就是说这个路由要用什么URL地址来访问。
                                Redirect = item.Redirect,//重定向地址
                                Meta = new UserMenuMeta()//元数据
                                {
                                    Title = item.Title,//显示名称。展示在菜单，标签和面包屑等中
                                    Active = item.Active,//左侧菜单的路由地址活动状态，比如打开详情页需要列表页的菜单活动状态
                                    Hidden = item.Hidden,//是否隐藏菜单，大部分用在无需显示在左侧菜单中的页面，比如详情页
                                    Icon = item.Icon,//显示图标，建立2级菜单都设置图标，否则菜单折叠都将显示空白
                                    Type = item.MenuType.GetDescription(),//类型：菜单，Iframe，外链
                                    FullPage = item.FullPage,//
                                    Affix = item.Affix,//是否固定，类似首页控制台在标签中是没有关闭按钮的
                                    Color = item.MenuColor,
                                }
                            };
                            userMenu.Children = GetMenuChildInfo(menuList, item.Id);//子集路由。
                            result.UserMenus.Add(userMenu);
                        }

                        #endregion

                        #region 获取可操作按钮权限
                        var roleMenuPermissions = await _menuPermissionRepository.GetManyAsync(x => true);
                        if (roleMenuPermissions.Any())
                        {
                            result.UserPermissions = roleMenuPermissions.Select(x => x.Code).ToList();
                        }
                        #endregion
                    }
                }
                else
                {
                    var userRoleList = await _userRoleRepository.GetManyAsync(x => x.UserId == userInfo.Id);
                    if (userRoleList.Any())
                    {
                        var roleIdList = userRoleList.Select(x => x.RoleId).ToList();
                        var menuList = await _menuRepository.GetMenuListByRole(new GetMenuListByRoleInDto()
                        {
                            RoleIdList = roleIdList,
                            Platform = input.Platform
                        },true);
                        if (menuList.Any())
                        {
                            #region UserMenus
                            var roots = menuList.Where(x => !x.ParentId.HasValue).ToList();
                            foreach (var item in roots)
                            {
                                var userMenu = new UserMenuInfo()
                                {
                                    Component = item.Component,//加载的页面组件位置，系统将自动组装成() => import(/* webpackChunkName: "home" */ '@/views/home') 的形式。
                                    Name = item.Name,//路由的标识，必填且与页面组件的name一致，否则 < keep - alive > 页面缓存效果失效。
                                    Path = item.Path,//路由在游览器地址栏里的hash值，也就是说这个路由要用什么URL地址来访问。
                                    Redirect = item.Redirect,//重定向地址
                                    Meta = new UserMenuMeta()//元数据
                                    {
                                        Title = item.Title,//显示名称。展示在菜单，标签和面包屑等中
                                        Active = item.Active,//左侧菜单的路由地址活动状态，比如打开详情页需要列表页的菜单活动状态
                                        Hidden = item.Hidden,//是否隐藏菜单，大部分用在无需显示在左侧菜单中的页面，比如详情页
                                        Icon = item.Icon,//显示图标，建立2级菜单都设置图标，否则菜单折叠都将显示空白
                                        Type = item.MenuType.GetDescription(),//类型：菜单，Iframe，外链
                                        FullPage = item.FullPage,//
                                        Affix = item.Affix,//是否固定，类似首页控制台在标签中是没有关闭按钮的
                                        Color = item.MenuColor,
                                    }
                                };
                                userMenu.Children = GetMenuChildInfo(menuList, item.Id);//子集路由。
                                result.UserMenus.Add(userMenu);
                            }
                            #endregion

                            #region 获取可操作按钮权限
                            var roleMenuPermissions = await _menuRepository.GetMenuPermissionListByRole(
                                                            new GetMenuPermissionListByRoleInDto()
                                                            {
                                                                RoleIdList = roleIdList
                                                            }, true);
                            if (roleMenuPermissions.Any())
                            {
                                result.UserPermissions = roleMenuPermissions.Select(x => x.Code).ToList();
                            }
                            #endregion
                        }
                    }
                }

                return result;
            });
        }

        /// <summary>
        /// 指定ID ，向下查询菜单所有的子节点------递归获取
        /// </summary>
        /// <param name="orgList"></param>
        /// <param name="parentId"></param>
        /// <returns></returns>
        private List<UserMenuInfo> GetMenuChildInfo(List<MenuInfoEntity> orgList, Guid parentId)
        {
            var reultList = new List<UserMenuInfo>();
            //根据NodeID，获取当前子节点列表
            UserMenuInfo treeInfo = null;

            var chidList = orgList.FindAll(x => x.ParentId == parentId).ToList();
            if (chidList.Any())
            {
                foreach (var item in chidList)
                {
                    treeInfo = new UserMenuInfo()
                    {
                        Component = item.Component,
                        Name = item.Name,
                        Path = item.Path,
                        Redirect = item.Redirect,//重定向地址
                        Meta = new UserMenuMeta()
                        {
                            Title = item.Title,
                            Active = item.Active,
                            FullPage = item.FullPage,
                            Affix = item.Affix,
                            Hidden = item.Hidden,
                            Icon = item.Icon,
                            Type = item.MenuType.GetDescription(),
                            Color = item.MenuColor,
                        }
                    };
                    //递归获取下一级
                    treeInfo.Children = GetMenuChildInfo(orgList, item.Id);
                    reultList.Add(treeInfo);
                }
            }
            return reultList;
        }

        #endregion

        #region 获取菜单树列表

        /// <summary>
        /// 获取菜单树列表
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<List<GetMenuTreeListOutput>>> GetMenuTreeList(GetMenuTreeListInput input)
        {
            return await HandleAsync(input, async () =>
            {
                var result = new List<GetMenuTreeListOutput>();

                var spceifications = new GetMenuListSpceification(input.Keywords, input.Platform).SatisfiedBy();
                var menuList = await _menuRepository.GetMenuList(spceifications, input.ReadOnly);

                if (menuList.Any())
                {
                    var roots = new List<GetMenuDetailListOutDto>();
                    if (menuList.Exists(x => !x.ParentId.HasValue))
                    {
                        roots = menuList.Where(x => !x.ParentId.HasValue).ToList();
                    }
                    else
                    {
                        var idList = menuList.Select(x => x.Id).Distinct().ToList();
                        roots = menuList.Where(x => !idList.Contains(x.ParentId.Value)).ToList();
                    }
                    result = MapperHelper<GetMenuDetailListOutDto, GetMenuTreeListOutput>.MapList(roots);

                    if (result.Count == 1)
                    {
                        result[0].CanUp = false;
                        result[0].CanDown = false;
                        GetChildMenu(result[0], menuList);
                    }
                    else
                    {

                        for (int i = 0; i < result.Count; i++)
                        {
                            if (i == 0)
                            {
                                result[i].CanUp = false;
                                result[i].CanDown = true;
                            }
                            else if (i == result.Count - 1)
                            {
                                result[i].CanUp = true;
                                result[i].CanDown = false;
                            }
                            else
                            {
                                result[i].CanUp = true;
                                result[i].CanDown = true;
                            }
                            GetChildMenu(result[i], menuList);
                        }
                    }
                }
                return result;
            });
        }

        /// <summary>
        /// 获取子节点
        /// </summary>
        /// <param name="root"></param>
        /// <param name="dataList"></param>
        private void GetChildMenu(GetMenuTreeListOutput root, List<GetMenuDetailListOutDto> dataList)
        {
            var childrens = dataList.Where(x => x.ParentId == root.Id).OrderBy(x => x.Sort).ToList();
            if (childrens.Any())
            {
                var parents = MapperHelper<GetMenuDetailListOutDto, GetMenuTreeListOutput>.MapList(childrens);
                root.Children = parents;

                if (parents.Count == 1)
                {
                    parents[0].CanUp = false;
                    parents[0].CanDown = false;
                    GetChildMenu(parents[0], dataList);
                }
                else
                {
                    for (int i = 0; i < parents.Count; i++)
                    {
                        if (i == 0)
                        {
                            parents[i].CanUp = false;
                            parents[i].CanDown = true;
                        }
                        else if (i == parents.Count - 1)
                        {
                            parents[i].CanUp = true;
                            parents[i].CanDown = false;
                        }
                        else
                        {
                            parents[i].CanUp = true;
                            parents[i].CanDown = true;
                        }
                        GetChildMenu(parents[i], dataList);
                    }
                }
            }
        }

        #endregion

        #region 获取角色对应菜单信息【所有菜单+可操作标识】

        /// <summary>
        /// 获取角色对应可操作权限信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<List<GetRoleMenuPermissionOutDto>>> GetMenuPermissionListByRole(GetMenuPermissionListByRoleInput input)
        {
            return await HandleAsync(async () =>
            {

                var roleIdList = new List<Guid>() { input.RoleId };
                var roleMenuPermissions = await _menuRepository.GetMenuPermissionListByRole(
                                                new GetMenuPermissionListByRoleInDto()
                                                {
                                                    RoleIdList = roleIdList
                                                }, input.ReadOnly);
                return roleMenuPermissions;
            });
        }

        /// <summary>
        /// 获取角色对应菜单信息【所有菜单+可操作标识】
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<BaseApiResult<List<GetMenuTreeByRoleOutput>>> GetMenuTreeByRole(GetMenuTreeByRoleInput input)
        {
            return await HandleAsync(async () =>
            {
                var result = new List<GetMenuTreeByRoleOutput>();

                var roleIdList = new List<Guid>() { input.RoleId };
                var menuList = await _menuRepository.GetMenuListByPlatform(new GetMenuListByPlatformInDto()
                {
                    RoleIdList = roleIdList,
                    Platform = input.Platform
                }, input.ReadOnly);

                if (menuList.Any())
                {
                    if (menuList.Exists(x => !x.ParentId.HasValue))
                    {
                        result = MapperHelper<GetMenuTreeByPlatformOutDto, GetMenuTreeByRoleOutput>.MapList(menuList.Where(x => !x.ParentId.HasValue).ToList());
                    }
                    else
                    {
                        var idList = menuList.Select(x => x.Id).Distinct().ToList();
                        result = MapperHelper<GetMenuTreeByPlatformOutDto, GetMenuTreeByRoleOutput>.MapList(menuList.Where(x => !idList.Contains(x.ParentId.Value)).ToList());
                    }
                    foreach (var item in result)
                    {
                        GetChildRoleMenu(item, menuList);
                    }
                }
                return result;
            });
        }

        /// <summary>
        /// 获取子节点
        /// </summary>
        /// <param name="root"></param>
        /// <param name="dataList"></param>
        private void GetChildRoleMenu(GetMenuTreeByRoleOutput root, List<GetMenuTreeByPlatformOutDto> dataList)
        {
            var childrens = dataList.Where(x => x.ParentId == root.Id).OrderBy(x => x.Sort).ToList();
            if (childrens.Any())
            {
                var parents = MapperHelper<GetMenuTreeByPlatformOutDto, GetMenuTreeByRoleOutput>.MapList(childrens);
                root.Children = parents;

                foreach (var item in parents)
                {
                    GetChildRoleMenu(item, dataList);
                }
            }
        }
        #endregion

    }
}
